﻿using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using RotaractProjectCalendar.DataAccessLayer;
using RotaractProjectCalendar.Models;

namespace RotaractProjectCalendar.Areas.Admin.Controllers
{
    [Authorize(Roles = "Admin")]
    public class ClubController : Controller
    {
        private readonly CalendarContext _db = new CalendarContext();

        //
        // GET: /Admin/Club/
        public async Task<ActionResult> Index()
        {
            var clubs = _db.Clubs.Select(c => c);

            return View(await clubs.ToListAsync());
        }

        //
        // GET: /Admin/Club/Details/5
        public async Task<ActionResult> Details(int? id)
        {
            if(id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            var club = await _db.Clubs.FindAsync(id);
            if(club == null)
            {
                return HttpNotFound();
            }
            return View(club);
        }

        //
        // GET: /Admin/Club/Create
        public ActionResult Create()
        {
            return View();
        }

        //
        // POST: /Admin/Club/Create
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Create([Bind(Include = "ClubTitle,Logo,FbProfileAddress,WwwWebsiteAddress,ClubEmailAddress")] Club club)
        {
            club.Coordinators = new List<Coordinator>();
            club.Projects = new List<Project>();
            club.Logo = "~/Content/Images/rac.jpg";

            try
            {
                if(ModelState.IsValid)
                {
                    foreach(var upload in Request.Files.Cast<string>()
                        .Where(upload => HasFile(Request.Files[upload])))
                    {
                        const string path = "~/Content/Images/";

                        var httpPostedFileBase = Request.Files[upload];

                        Debug.Assert(httpPostedFileBase != null, "httpPostedFileBase != null");
                        var filename = Path.GetFileName(httpPostedFileBase.FileName);

                        if(!httpPostedFileBase.ContentType.StartsWith("image"))
                        {
                            ModelState.AddModelError("", "Unable to create event. The attachment have to an image.");
                            return View(club);
                        }

                        if(httpPostedFileBase.ContentLength > 3000000)
                        {
                            ModelState.AddModelError("", "Unable to create event. The attachment is too big. Maximum size of the file 3 MB.");
                            return View(club);
                        }

                        if(filename == null)
                        {
                            continue;
                        }

                        httpPostedFileBase.SaveAs(Server.MapPath(Path.Combine(path, filename)));

                        club.Logo = Path.Combine(path, filename);
                    }

                    _db.Clubs.Add(club);
                    await _db.SaveChangesAsync();
                    return RedirectToAction("Index");
                }
            }
            catch(RetryLimitExceededException /* dex */)
            {
                //Log the error (uncomment dex variable name and add a line here to write a log.
                ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
            }
            return View(club);
        }

        //
        // GET: /Admin/Club/Edit/5
        public async Task<ActionResult> Edit(int? id)
        {
            if(id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            var club = await _db.Clubs.FindAsync(id);
            if(club == null)
            {
                return HttpNotFound();
            }
            return View(club);
        }

        //
        // POST: /Admin/Club/Edit/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Edit([Bind(Include = "ID,ClubTitle,Logo,FbProfileAddress,WwwWebsiteAddress,ClubEmailAddress")] Club club)
        {
            try
            {
                if(ModelState.IsValid)
                {
                    foreach(var upload in Request.Files.Cast<string>()
                        .Where(upload => HasFile(Request.Files[upload])))
                    {
                        const string path = "~/Content/Images/";

                        var httpPostedFileBase = Request.Files[upload];

                        Debug.Assert(httpPostedFileBase != null, "httpPostedFileBase != null");
                        var filename = Path.GetFileName(httpPostedFileBase.FileName);

                        if(!httpPostedFileBase.ContentType.StartsWith("image"))
                        {
                            ModelState.AddModelError("", "Unable to save changes. The attachment have one of the selected type: .jpg, .png or .gif");
                            return View(club);
                        }

                        if(httpPostedFileBase.ContentLength > 3000000)
                        {
                            ModelState.AddModelError("", "Unable to save changes. The attachment is too big. Maximum size of the file 3 MB.");
                            return View(club);
                        }

                        if(filename == null)
                        {
                            continue;
                        }
                        
                        httpPostedFileBase.SaveAs(Server.MapPath(Path.Combine(path, filename)));

                        club.Logo = Path.Combine(path, filename);
                    }

                    _db.Entry(club).State = EntityState.Modified;
                    await _db.SaveChangesAsync();
                    return RedirectToAction("Index");
                }
            }
            catch(RetryLimitExceededException /* dex */)
            {
                //Log the error (uncomment dex variable name and add a line here to write a log.
                ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
            }
            return View(club);
        }

        //
        // GET: /Admin/Club/Delete/5
        public async Task<ActionResult> Delete(int? id, bool? saveChangesError = false)
        {
            if(id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            if(saveChangesError.GetValueOrDefault())
            {
                ViewBag.ErrorMessage = "Deleted failed. Try again, and if the problem persist see your system administrator.";
            }
            var club = await _db.Clubs.FindAsync(id);
            if(club == null)
            {
                return HttpNotFound();
            }
            return View(club);
        }

        //
        // POST: /Admin/Club/Delete/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Delete(int id)
        {
            try
            {
                //Club club = await db.Clubs.FindAsync(id);
                //db.Clubs.Remove(club);
                //Below code improves performance by avoiding unnecessary SQL query
                var clubToDelete = new Club { Id = id };
                _db.Entry(clubToDelete).State = EntityState.Deleted;
                await _db.SaveChangesAsync();
            }
            catch(RetryLimitExceededException /* dex */)
            {
                //Log the error (uncomment dex variable name and add a line here to write a log.
                return RedirectToAction("Delete", new { id, saveChangesError = true });
            }
            return RedirectToAction("Index");
        }

        [ChildActionOnly]
        private static bool HasFile(HttpPostedFileBase file)
        {
            return (file != null && file.ContentLength > 1);
        }

        protected override void Dispose(bool disposing)
        {
            if(disposing)
            {
                _db.Dispose();
            }
            base.Dispose(disposing);
        }
	}
}